// *********************************************************************************
// Project Name : zkx2024
// Author       : xfsong
// Email        : 1293993416@qq.com
// Create Time  : 2024-04-22
// File Name    : share_cac.v
// Module Name  :
// Called By    :
// Abstract     :
//
// 
// *********************************************************************************
// Modification History:
// Date         By              Version                 Change Description
// -----------------------------------------------------------------------
// 2024-04-22    Macro           1.0                     Original
//  
// *********************************************************************************

    
module share_cac(
    input CLK, RST_N,
    output reg [0:0]  FULL_CAC, EMPTY_CAC,

    dsp_cac_bus.cac_ports share_cac_ports
);

//parameter INT_ADDR = 13'd0;// .... (0~1k-1  1k~2k-1  2k~3k-1 3k~4k-1.....7k~8k-1) base-addr: 0 1k 2k 3k 4k .....7k
parameter INT_PRIO_ADDR = 3'd1; // for 13-bit address 0-9 represent detailed address, 10-12 keep a fixed value. here is the fix value for different priority.

//-----------------------active_wr_addr
reg [8:0]   wr_data_room; //represent how many sram rom addrs are used for one data in, max 1024byte/4byte = 256 -> 1-256 9bit
reg [10:0]  active_wr_addr;  //just care low 10bit of address in data_value, 10bit is enough to represent data depth, but add one more bit for address reverse
always@(*)begin
    wr_data_room = 9'b0;
    if(share_cac_ports.WR_DATA_VLD_CAC == 1'b1)begin
        if(share_cac_ports.WR_DATA_VALUE_CAC[1:0]!= 2'b00)
            wr_data_room = (share_cac_ports.WR_DATA_VALUE_CAC[9:2] + 1'b1);
        else
            wr_data_room = share_cac_ports.WR_DATA_VALUE_CAC[9:2];
    end
end

always@(posedge CLK or negedge RST_N)begin
    if(!RST_N)
        active_wr_addr <= 11'b0;
    else if(share_cac_ports.CAC_SRAM[5] == 1'b0)   //when the share_cac is not occupied, cac_sram[5] should be 0
        active_wr_addr <= 11'b0;
    else if(share_cac_ports.WR_DATA_VLD_CAC)begin
        if(share_cac_ports.WR_DATA_VALUE_CAC[29:28] == 2'b00)
            active_wr_addr <= active_wr_addr + wr_data_room;// full logic loading here
    end
end

//-----------------------active_rd_addr
reg [8:0] rd_data_room;
reg [10:0] active_rd_addr;
always@(*)begin
    rd_data_room = 8'b0;
    if(share_cac_ports.RD_DATA_VLD_CAC == 1'b1)begin
        if(share_cac_ports.RD_DATA_VALUE_CAC[1:0]!= 2'b00)
            rd_data_room = (share_cac_ports.RD_DATA_VALUE_CAC[9:2] + 1'b1);
        else
            rd_data_room = share_cac_ports.RD_DATA_VALUE_CAC[9:2];
    end
end

always@(posedge CLK or negedge RST_N)begin
    if(!RST_N)
        active_rd_addr <= 11'b0;
    else if(share_cac_ports.CAC_SRAM[5] == 1'b0)   //when the share_cac is not occupied, cac_sram[5] should be 0 and rd_addr should be reset
        active_rd_addr <= 11'b0;
    else if(share_cac_ports.RD_DATA_VLD_CAC)begin
        if(share_cac_ports.RD_DATA_VALUE_CAC[29:28] == 2'b10)
            active_rd_addr <= active_rd_addr + rd_data_room;//
    end
end

//-----------------------real wr_addr
assign wr_addr = {INT_PRIO_ADDR,active_wr_addr[9:0]};

//-----------------------return wr_addr_cac
always@(posedge CLK or negedge RST_N)begin
    if(!RST_N)begin
       share_cac_ports.WR_ADDR_CAC <= 18'd0;
       share_cac_ports.WR_VLD_CAC <= 1'b0;
    end
    else if(share_cac_ports.WR_REQ_CAC)begin
       share_cac_ports.WR_ADDR_CAC <= {share_cac_ports.CAC_SRAM[4:0],wr_addr};
       share_cac_ports.WR_VLD_CAC <= 1'b0;
    end
end

//-----------------------calcuate space left
reg [10:0] room_left;
//reg [9:0] room_left;
always@(*)begin
    if(active_rd_addr[10] == active_wr_addr[10])
        room_left = 11'd1024 - active_wr_addr[9:0] + active_rd_addr[9:0];
    else
        room_left = active_rd_addr[9:0] - active_wr_addr[9:0];
end

        
//-----------------------full logic
always@(*)begin
    if(room_left < 256)
        FULL_CAC = 1'b1;
    else
        FULL_CAC = 1'b0;
end
//-----------------------empty logic -----for fix_cac



//-----------------------empty logic -----for share_cac
//-------empty_lock
reg empty_lock;
always@(posedge CLK or negedge RST_N)begin
    if(!RST_N)
        empty_lock <= 1'b0;
    else if(share_cac_ports.CAC_SHARE == 1'b1)
        empty_lock <= 1'b1;
    else if(share_cac_ports.WR_DATA_VLD_CAC)
        empty_lock <= 1'b0;
end

always@(*)begin
    EMPTY_CAC = 1'b0;
    if(!share_cac_ports.CAC_SHARE && !empty_lock)begin
        if(active_wr_addr == active_rd_addr)
            EMPTY_CAC = 1'b1;
    end
end

endmodule
